home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / asmexam.arc / FREE.ASM < prev    next >
Assembly Source File  |  1983-11-17  |  9KB  |  217 lines

  1.          name     free
  2.          page     60,132
  3.          title    'FREE --- report free space on disk'
  4.  
  5. ;FREE --- a utility to report free space on
  6. ;        the default or selected disk drive.
  7. ;
  8. ;Requires PC-DOS or MS-DOS 2.0
  9. ;
  10. ;Used in the form:
  11. ;A>FREE [unit:]
  12. ;(item in square brackets is optional)
  13. ;
  14. ;version 1.0 July 1, 1984
  15. ;Copyright (c) 1984 by Ray Duncan
  16. ;May be freely reproduced for non-commercial use.
  17.  
  18. cr       equ            0dh                 ;ASCII carriage return
  19. lf       equ            0ah                 ;ASCII line feed
  20. blank    equ            20h                 ;ASCII space code
  21. eom      equ            '$'                 ;end of string marker
  22.  
  23.  
  24. ;Here we define a dummy segment containing lavbels
  25. ;for thedefault fiel control black and the command tail buffer,
  26. ;so that the main program can access those locations.
  27. ;
  28. psp      segment para public 'PSP'
  29.  
  30.          org            05ch
  31. fcb      label          byte                ;default file control block
  32.  
  33.          org            080h
  34. command  label          byte                ;default command buffer
  35.  
  36. psp      ends
  37.  
  38. cseg     segment para public'CODE'
  39.  
  40.          assume cs:cseg,ds:psp,es:data,ss:stack
  41.  
  42. get_drive proc near                         ;get drive selection, if any,
  43.                                             ;otherwise obtain the identity
  44.                                             ;of the current disk drive.
  45.                                             ;Return drive (1=A,2=B,etc)in RL.
  46.                                             ;
  47.          mov            al,fcb              ;Pick up the drive code, parsed
  48.                                             ;by DOS into the default file
  49.                                             ;control block.
  50.          or             al,al               ;Is it the default?
  51.          jnz            get_drive1          ;no, use it
  52.          mov            ah,19h              ;Yes, get the actual current
  53.          int            21h                 ;drive from PC-DOS.
  54.          inc            al                  ;Increment to match FCB code.
  55. get_drive1:                                 ;Return drive code in RL.
  56.          ret
  57. get_drive endp
  58.  
  59. free     proc           far                 ;entry point from PC-DOS
  60.          push           ds                  ;Save OS:0000 for final
  61.          xor            ax,ax               ;return to PC-DOS
  62.          push           ax
  63.          mov            ax,data             ;make our data segment
  64.          mov            es,ax               ;addressable via ES register.
  65.          mov            ah,30h              ;check version of PC-DOS.
  66.          int            21h
  67.          cmp            al,2
  68.          jae            free1               ;proceed, DOS 2.0 or greater.
  69.          mov            dx,offset msg2      ;DOS 1.x -- print error message
  70.          mov            ax,es               ;and exit. First fix up DS register
  71.          mov            ds,ax               ;;so error message is addressable.
  72.          jmp            free1
  73.  
  74. free1:   call           get_drive           ;get drive selection into DL.
  75.          push           es                  ;copy ES to Ds for remainder
  76.          pop            ds                  ;of the program...
  77.          assume         ds:data             ;and tell assembler about it.
  78.          mov            dl,al
  79.          add            al,'A'-1            ;form drive letter from drive soce,
  80.          mov            outputb,al          ;and put i into the ouput string.
  81.          mov            ah,36h              ;nob call dos to get free disk space
  82.          int            21h
  83.          cmp            ax,-1               ;was drive invalid?
  84.          je             free3               ;yes, go print error message
  85.                                             ;drive was ok, so now registers are.
  86.  
  87.                                             ;RX=number of sectors per cluser
  88.                                             ;BX=available clusters,
  89.                                             ;CX=number of bytes per sector,
  90.                                             ;DX=total clusters per drive.
  91.                                             ;calculate free space:
  92.          mul            cx                  ;sectors per cluster * bytes/sector
  93.                                             ;(we assume no overflow into DX
  94.          mul            bx                  ;then* available clusers
  95.          mov            si,offset (outputa+9)
  96.          mov            cx,10               ;CX = 10, radix for conversion
  97.          call           bin_to_asc          ;convert free space value to ASCII,
  98.          mov            dx,offset output
  99.          jmp            free4               ;and print it out.
  100.  
  101. free3:   mov            dx,offset msg1      ;illegal drive, print error
  102.  
  103. free4:   mov            ah,9                ;prin the string whose address
  104.          int            21h                 ;is in DX.
  105.          ret                                ;then return to DOS.
  106.  
  107. free   endp
  108.  
  109. ;Convert 32 bit binary value to ASCII string.
  110. ;
  111. ;Call with DX:AX = signed 32 but value
  112. ;        CX  =          radix
  113. ;        SI  =          last byte of area to store resulting string
  114. ;                       (make sure enough room is available to store
  115. ;                       the string in the radix you have selected.)
  116. ;
  117. ;Destroys RX,BX,CX,DX, and SI.
  118. ;
  119. bin_to_asc proc near                        ;convert DX:AX to ASCII.
  120.                                             ;force storage of at least 1 digit.
  121.          mov            byte ptr [si],'0'
  122.          or             dx,dx               ;test sign of 32 bit value,
  123.          pushf                              ;and save sign on stack.
  124.          jns            bin1                ;jump if it was positive.
  125.          not            dx                  ;it was negative, take 2's complemen
  126.  
  127.          not            ax                  ;of the value.
  128.          add            ax,1
  129.          adc            dx,0
  130. bin1:                                       ;divide the 32 bit balue by the radi
  131.  
  132.                                             ;to extract the next digit for the
  133.                                             ;forming string.
  134.          mov            bx,ax               ;is the value zero yet?
  135.          or             bx,dx
  136.          jz             bin3                ;yes, we are done converting.
  137.          call           divide              ;no, divide by radix.
  138.          add            bl,'0'              ;convert the remainder to an ASCII
  139.          cmp            bl,'9'              ;we might be converting to hex ASCII
  140.  
  141.          jle            bin2                ;jump if in range 0-9,
  142.          add            bl,'A'-'9'-1        ;correct it if in range A-F.
  143. bin2:    mov            [si],bl             ;store this character into string.
  144.                                             ;to extract the next digit for the
  145.                                             ;forming string.
  146.          dec            si                  ;back up throught string,
  147.          jmp            bin1                ;and so it again.
  148. bin3:                                       ;restore sign flag,
  149.          popf                               ;was original value negative?
  150.          jns            bin4                ;no, jump
  151.                                             ;yes, store sign into ouput string.
  152.          mov            byte ptr[si],'-'
  153. bin4:    ret                                ;back to caller.
  154. bin_to_asc endp
  155.  
  156.  
  157. ;General purpose 32 bit by 16 bit unsigned divide.
  158. ;This must be used instead of the plain machine unsigned divide
  159. ;for cases where the quotient may overflow 16 bits (for example,
  160. ;dividing 100,000 by 2).  If called with a zero divisor, this
  161. ;routine returns the dividend unchanged and gives no warning.
  162. ;
  163. ;Call with     DX:AX = 32 bit dividend
  164. ;              CX    = divisor
  165. ;
  166. ;Returns        DX:AX = quotient
  167. ;              BX = remainder
  168. ;              CX = divisor (unchanged)
  169. ;
  170.  
  171. divide   proc           near                ;Divide DX:AX by CX
  172.          jcxz           div1                ;exit if divide by zero
  173.          push           ax                  ;0:dividend_upper/divisor
  174.          mov            ax,dx
  175.          xor            dx,dx
  176.          div            cx
  177.          mov            bx,ax               ;BX = quotient1
  178.          pop            ax                  ;remainder1:dividend_lower.divisor
  179.          div            cx
  180.          xchg           bx,dx               ;DX:RX = quotient1:quotient2
  181. div1:    ret                                ;BX = remainder2
  182. divide   endp
  183. cseg     ends
  184.  
  185.  
  186. data     segment para public 'DATA'
  187.  
  188. output   db      cr,lf
  189. outputa  db      10 dup(blank)
  190.  
  191.  
  192.          db      'bytes free on drive'
  193.  
  194.  
  195. outputb  db      'x:',cr,lf,eom
  196.  
  197. msg1     db      cr,lf
  198.          db      'That disk drive does not exist.'
  199.  
  200.  
  201.          db      cr,lf,eom
  202.  
  203. msg2     db      cr,lf
  204.          db      'Requires DOS version 2 or greater.'
  205.  
  206.  
  207.  
  208.          db      cr,lf,eom
  209. data     ends
  210.  
  211. stack    segment para stack 'STACK'
  212.          db      64 dup (?)
  213.  
  214. stack    ends
  215.  
  216.          end free
  217.